There are n sticks lying on the ground. The
Ant can move only along the sticks. It can go from one stick to another only if
the sticks intersect or touch each other. Help the Ant find out if it can reach
the stick y from the
stick x.
Input. The first line
of the input contains number t (1 ≤ t ≤ 100) – the amount of tests. Then t test descriptions follow. The first line of each test
contains two integers n and m (1 ≤ n, m ≤ 1000) – the number of stick and the number of queries. Next n lines contain four integers Ax, Ay,
Bx, By (-10000 ≤
Ax, Ay, Bx, By ≤ 10000) – the coordinates
of the endpoints of a stick. You may consider stick to be straight segment on a
plane. The next m lines contain two
integers each x and y (1 ≤ x, y ≤ n) which are the queries.
Output. For each query
print "YES" if the Ant can reach the stick number y from the
stick number x, otherwise print "NO".
Sample Input |
Sample Output |
2 3 3 1 3 4 3 3 4 3 1 3 1 5 1 1 2 1 3 2 2 3 3 1 1 3 1 2 1 3 1 3 2 4 1 1 2 1 3 2 3 |
YES |
геометрия + связность
На плоскости расположено множество палочек
(отрезков). Муравей может переползти с одной палочки на другую только если они
пересекаются. Определить, сможет ли муравей переползти с палочки y на палочку x.
Рассмотрим
граф, в котором вершинам соответсвуют палочки. Между вершинами x и y существует ребро только если x и y пересекаются.
Реализация алгоритма
#include <stdio.h>
#define MAX 1010
int x, y, tests, n, m, i, j;
int ax[MAX], ay[MAX], bx[MAX], by[MAX];
int mas[MAX];
int RectanglesIntersects(int x1, int y1, int x2, int y2,
int x3, int y3, int x4, int y4)
{
if ((x3 - x2)*(x4 - x1) > 0) return 0;
if ((y3 - y2)*(y4 - y1) > 0) return 0;
return 1;
}
int min(int x, int y)
{
return (x < y) ? x : y;
}
int max(int x, int y)
{
return (x > y) ? x : y;
}
int sgn(int x)
{
return (x > 0) - (x < 0);
}
// A = (x1,y1),
B = (x2,y2), C(x3,y3), D(x4,y4)
// return 1, if
segments intersect
int intersect(int x1, int y1, int x2, int y2,
int x3, int y3, int x4, int y4)
{
int ABx, ABy, ACx, ACy, ADx, ADy;
int CAx, CAy, CBx, CBy, CDx, CDy;
int ACxAB, ADxAB, CAxCD, CBxCD;
if (!RectanglesIntersects(min(x1, x2), min(y1, y2), max(x1, x2), max(y1,
y2), min(x3, x4), min(y3, y4), max(x3, x4), max(y3, y4))) return 0;
ACx = x3 - x1; ACy = y3 - y1;
ABx = x2 - x1; ABy = y2 - y1;
ADx = x4 - x1; ADy = y4 - y1;
CAx = x1 - x3; CAy = y1 - y3;
CBx = x2 - x3; CBy = y2 - y3;
CDx = x4 - x3; CDy = y4 - y3;
ACxAB = ACx * ABy - ACy * ABx;
ADxAB = ADx * ABy - ADy * ABx;
CAxCD = CAx * CDy - CAy * CDx;
CBxCD = CBx * CDy - CBy * CDx;
if ((sgn(ACxAB) * sgn(ADxAB) > 0) || (sgn(CAxCD) * sgn(CBxCD) > 0))
return 0;
return 1;
}
int Repr(int n)
{
if (n == mas[n]) return n;
return mas[n] =
Repr(mas[n]);
}
int Union(int x, int y)
{
int x1 = Repr(x), y1 = Repr(y);
mas[x1] = y1;
return (x1 != y1);
}
int main(void)
{
scanf("%d", &tests);
while (tests--)
{
scanf("%d %d", &n,
&m);
for (i = 1; i <= n; i++)
scanf("%d %d %d %d",
&ax[i], &ay[i], &bx[i], &by[i]);
for (i = 1; i <= n; i++) mas[i] = i;
for (i = 1; i <= n; i++)
for (j = i + 1; j <= n; j++)
if
(intersect(ax[i], ay[i], bx[i], by[i], ax[j], ay[j], bx[j], by[j]))
Union(i, j);
for (i = 0; i < m; i++)
{
scanf("%d %d", &x,
&y);
if (Repr(x) ==
Repr(y)) puts("YES");
else puts("NO");
}
}
return 0;
}